package com.DosonLeung.homeschoolcommunication.Services;

import android.app.Service;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.DosonLeung.homeschoolcommunication.Constant.SystemConstant;
import com.DosonLeung.homeschoolcommunication.Constant.UrlConstant;
import com.DosonLeung.homeschoolcommunication.Constant.UserConstant;
import com.DosonLeung.homeschoolcommunication.Utils.NetWorkUtil;
import com.DosonLeung.homeschoolcommunication.Utils.StorageUtil;
import com.DosonLeung.homeschoolcommunication.Utils.TimeUtil;
import com.DosonLeung.homeschoolcommunication.Utils.UpdataUtil;
import com.github.nkzawa.emitter.Emitter;
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

/**
 * Created by SherlockZhong on 11/29/14.
 */
public class SocketService {
    public String host = "http://120.24.58.118:3000/"; // 测试服务器ip 121.40.202.14, 生产服务器ip 120.24.58.118
    public Socket socket = null;
    private Service mainService = null;
    private Handler mainServiceHandler = null;
    //暂存数据的哈希表
    private LinkedList<HashMap<String,String>> dataQueue;
    //下载队列
    private ArrayList<HashMap<String,String>> downloadQueue;
    //上传队列
    private ArrayList<HashMap<String,String>> uploadQueue;
    //service状态
    private boolean status = false;

    public SocketService (Service service, Handler handler) {
        mainService = service;
        mainServiceHandler = handler;
        this.dataQueue = new LinkedList<HashMap<String, String>>();
        this.downloadQueue = new ArrayList<HashMap<String, String>>();
        this.uploadQueue = new ArrayList<HashMap<String, String>>();
    }

    //Socket把消息存放至消息队列
    private void insertData(JSONObject jsonObject){
        HashMap<String,String> data = new HashMap<String,String>();
        try {
            data.put("uid", jsonObject.getString("sender_uid"));
            data.put("contentType", jsonObject.getString("type"));
            data.put("time", TimeUtil.formatTime(jsonObject.getString("time")));
            data.put("content", jsonObject.getString("content"));
            data.put("url", (jsonObject.getString("type")).equals("text") ? "" : jsonObject.getString("content"));//text文本消息不需要url，但请保留为"";
            data.put("length", jsonObject.getString("cid"));
            data.put("level",jsonObject.getString("msg_type"));
            data.put("extra",jsonObject.getString("sender_uid"));
            dataQueue.add(data);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    //把需要下载的资源放置下载队列
    private void insertCache(JSONObject jsonObject){
        HashMap<String,String> data = new HashMap<String,String>();
        try {
            String url = (String)jsonObject.get("content");
            data.put("uid", jsonObject.getString("sender_uid"));
            data.put("contentType", jsonObject.getString("type"));
            data.put("time", TimeUtil.formatTime(jsonObject.getString("time")));
            data.put("content", url);
            data.put("url", url);//text文本消息不需要url，但请保留为"";
            data.put("length", jsonObject.getString("cid"));
            data.put("level",jsonObject.getString("msg_type"));
            data.put("extra",jsonObject.getString("sender_uid"));
            downloadQueue.add(data);
            downloadVoice(url);//开始下载资源
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public HashMap<String,String> getData(){
        HashMap<String, String> data = null;
        try {
            data = dataQueue.getFirst();
            dataQueue.removeFirst();
            status = false;
        }catch (Exception e){
            e.printStackTrace();
            status = false;
        }
        return data;
    }

    /**
     * 当Service可以处理信息时，该方法会被调用，并参数为true
     * 或者当Service处理完接收信息后，该方法将会被调用作反馈，true处理成功,false处理失败(处理失败意味程序
     * 存储处错误，属低概率事件，处理方法，重启)
     * 如果处理消息成功（按道理可以继续发送消息），但是用户推出登录，也会被调用并返回false，这样Socket也可以乐安
     * 天命了
     * 说白了，就是true可以接受信息，flase不可以接收信息，并且socket要自杀
     * */
    public void notify(boolean status){
        this.status = status;
        if(status){
            if(dataQueue.size()>0) {
                mainServiceHandler.sendEmptyMessage(0x200);
            }
        }else{
            disconnect();
            socket.close();
            Log.e("TestSocket","socket was closed!");
        }
    }

    public void start () {
        try {
            socket = IO.socket(host);
            socket.connect();
            socket.on(socket.EVENT_CONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    System.out.println("*****connected to server");
                    try {
                        JSONObject userInfo = new JSONObject();
                        userInfo.put("uid", UserConstant.USER_ID); // user id
                        userInfo.put("cid", UserConstant.CLASS_ID_LIST); // class id
                        userInfo.put("sid", UserConstant.USER_ACCOUNT); // account
                        userInfo.put("psw", UserConstant.USER_PASSWORD); // password
                        socket.emit("init", userInfo.toString());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).on(socket.EVENT_DISCONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    System.out.println("*****disconnected to server");
                }
            }).on(socket.EVENT_ERROR, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    System.out.println("*****error occured");
                }
            }).on("msg", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    try {
                        JSONObject jsonObject = new JSONObject(args[0].toString());
                        //老师不接收班级信息
                        if(UserConstant.USER_CHARACTER.equals("patriarch")||jsonObject.getString("cid").equals("")) {
                            if (jsonObject.getString("type").equals("audio")) {
                                insertCache(jsonObject);
                            } else {
                                insertData(jsonObject);
                                if (status) {
                                    mainServiceHandler.sendEmptyMessage(0x200);
                                } else {
                                    Log.e("SocketService", "System can't receieve the news now");
                                }
                            }
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }).on("conflict", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    mainServiceHandler.sendEmptyMessage(SystemConstant.LOG_STRANGE);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void connect () {
        socket.connect();
    }

    public void disconnect () {
        socket.disconnect();
    }

    public void sendData(JSONObject data) {
        if(!socket.connected())
            socket.connect();
        socket.emit("msg", data.toString());
    }

    //下载声音文件
    private void downloadVoice(String url){
        //本地无法找不到文件,从网络提取
        final String link = url;
        new Thread() {
            public void run() {
                try {
                    String fileName = link.substring(link.lastIndexOf("/") + 1, link.lastIndexOf(".")) + ".acc";//从url中剪出文件名
                    String filePath = StorageUtil.getVoiceDir().toString()+"/"+fileName;
                    File file = new File(StorageUtil.getVoiceDir().toString());
                    if(!file.exists()){
                        file.mkdirs();
                    }
                    download(link,filePath);
                    Bundle bundle = new Bundle();
                    bundle.putString("url",link);
                    bundle.putString("filepath",filePath);
                    bundle.putBoolean("status",true);
                    Message msg = new Message();
                    msg.setData(bundle);
                    msg.what = 0x208;
                    mainServiceHandler.sendMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                    Bundle bundle = new Bundle();
                    bundle.putString("url",link);
                    bundle.putBoolean("status",false);
                    Message msg = new Message();
                    msg.setData(bundle);
                    msg.what = 0x408;
                    mainServiceHandler.sendMessage(msg);
                }
            }
        }.start();
    }

    //把downloadQueue里面的完成数据搬至dataQueue里,参数url为索引,status为下载结果
    public synchronized void moveDLQ2DQ(String url,String filePath,boolean status){
        Log.e("chatHandler in socketservice",mainService.toString());
        HashMap<String,String> data;
        int i;
        for(i = 0;i < downloadQueue.size();i++){
            data = downloadQueue.get(i);
            if(url.equals(data.get("url"))){
                if(status) {
                    data.remove("url");
                    data.put("url", filePath);
                }//将资源路径改为本地路径
                else{
                    Log.e("socket","downloaded failed");
                }
                break;
            }
        }
        dataQueue.add(downloadQueue.get(i));
        downloadQueue.remove(i);
        if (status) {
            mainServiceHandler.sendEmptyMessage(0x200);
        }else{
            Log.e("SocketService","System can't receieve the news now");
        }
    }

    protected void upLoadImage(HashMap<String, String> item){
        String url = item.get("url");
        String name = url.substring(url.lastIndexOf("/") + 1);
        item.put("name",name);
        uploadQueue.add(item);
        File file = new File(url);
        if(file.exists()){
            UpdataUtil.uploadFile(file,name,true,mainServiceHandler);
        }else{
            Toast.makeText(mainService,"上传失败,图片文件不存在",Toast.LENGTH_SHORT).show();
        }
    }

    protected void upLoadAudio(HashMap<String, String> item){
        String url = item.get("url");
        String name = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
        item.put("name",name);
        uploadQueue.add(item);
        File file = new File(url);
        if(file.exists()){
            UpdataUtil.uploadFile(file,name,false,mainServiceHandler);
        }else{
            Toast.makeText(mainService,"上传失败,音频文件不存在",Toast.LENGTH_SHORT).show();
        }
    }

    protected HashMap<String,String> take(String name){
        HashMap<String,String> item = null;
        String content;
        int i;
        for(i = 0;i< uploadQueue.size();i++){
            item = uploadQueue.get(i);
            if((item.get("name")).equals(name)){
                content = String.format(SystemConstant.DOWN_LOAD_IMAGE_PRE,name);
                item.remove("content");
                item.put("content",content);
                break;
            }
        }
        uploadQueue.remove(i);
        return item;
    }

    private void download(String Url,String filename){
        try {
            // 构造URL
            URL url = new URL(Url);
            // 打开连接
            URLConnection con = url.openConnection();
            // 获得文件的长度
            int contentLength = con.getContentLength();
            int doneLength = 0;
            System.out.println("长度 :" + contentLength);
            // 输入流
            InputStream is = con.getInputStream();
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流
            OutputStream os = new FileOutputStream(filename);
            // 开始读取
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            // 完毕，关闭所有链接
            os.close();
            is.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //接收历史消息
    protected void getHistory(){
        new Thread() {
            @Override
            public void run() {
                JSONArray jsonArray;
                JSONObject jsonObject;
                String result;
                String s;
                try {
                    result = NetWorkUtil.httpGet(String.format(UrlConstant.getHistoryUrl,UserConstant.USER_ACCOUNT,UserConstant.USER_PASSWORD));
                    JSONObject resultObject = new JSONObject(result);
                    jsonArray = resultObject.getJSONArray("messages");
                    int size = jsonArray.length();
                    for(int i = 0;i < size;i++){
                        s = jsonArray.getString(i);
                        jsonObject = new JSONObject(s);
                        if(jsonObject.getString("type").equals("audio")) {
                            insertCache(jsonObject);
                        }else {
                            insertData(jsonObject);
                        }
                    }
                    if(status)
                        mainServiceHandler.sendEmptyMessage(0x200);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

}
